﻿using System.Collections.ObjectModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Management;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Threading;
using CommunityToolkit.Mvvm.Messaging;
using DynamicData;
using Serilog;
using SimpleTool.ActivityUnit;
using SimpleTool.ActivityUnit.EchoControl;
using SimpleTool.Base;
using SimpleTool.Server;
using SimpleTool.TransformComponent;
using static SimpleTool.SerialTool.SerialControl.CommandSectionModel;
using static SimpleTool.SerialTool.SerialControl.ConfigSectionModel;

namespace SimpleTool.SerialTool.SerialControl
{

    public class SerialViewModel : Notify
    {
        //  下拉框期望展示的默认选项
        private string SelectedSerialProtStdin = string.Empty;

        private string SelectedBaudRateStdin = string.Empty;

        private string SelectedDataBitStdin = string.Empty;

        private string SelectedParityBitStdin = string.Empty;

        private string SelectedStopBitStdin = string.Empty;

        private string SelectedHandShakeStdin = string.Empty;

        private string ExecuteButtonTextStdin = "连接";

        private ICommand? CmdSerilconnectStdin;

        private ICommand? CmdSerialconfigChangeStdin;

        private ICommand? CmdSerialcommandAddStdin;

        private ICommand? CmdSerialcommandTakeStdin;

        private ICommand? CmdSerialcommandIndexStdin;

        private ICommand? CmdSerialcommandWriteStdin;

        private ICommand? CmdSerialcommandModeStdin;

        private ICommand? CmdSerialcommandImportStdin;

        private ICommand? CmdSerialcommandEditStdin;

        public class CommandChangeEventHandle(CommandSectionModel.AlterCommandStruct editInfo) : EventArgs
        {
            public AlterCommandStruct data = editInfo;
        }

        public SerialViewModel(ISerialServer _SerialServer,
                               IDirFileServer _DirFileServer,
                               IDataBaseServer _DataBaseServer,
                               IDenCryptoGraphicServer _DenCryptoGraphicServer,
                               IPowerPlantServer _PowerPlant)
        {
            SerialServer = _SerialServer;

            DirFileServer = _DirFileServer;

            DataBaseServer = _DataBaseServer;

            PowerPlantServer = _PowerPlant;

            CryptoGraphicSeriver = _DenCryptoGraphicServer;

            WeakReferenceMessenger.Default.Register<MvvmMessage>(this, MvvmMessageProcessPlant);

            Logger = Log.ForContext<SerialViewModel>();

            _= ReadyWork();
        }

        private readonly ISerialServer SerialServer;

        private readonly IDirFileServer DirFileServer;

        private readonly IDataBaseServer DataBaseServer;

        private readonly IDenCryptoGraphicServer CryptoGraphicSeriver;

        private readonly IPowerPlantServer PowerPlantServer;

        private CommandStruct? VarbinCurrentItemStdin = null;

        private SelectionMode VarbinListBoxModeStdin = SelectionMode.Single;

        private string VarbinListBoxModeNameStdin = "\ue64b";

        private ConfigSectionModel? ConfigTemplateModel = null;

        private CommandSectionModel? CommandTemplateModel = null;

        private readonly ILogger Logger;

        public ConfigSectionModel HoldConfigSectionModel
        {
            set
            {
                ConfigTemplateModel = value;
                propertyChangeSend(nameof(HoldConfigSectionModel));
            }
            get
            {
                ConfigTemplateModel ??= new ConfigSectionModel();
                return ConfigTemplateModel;
            }
        }

        public CommandSectionModel HoldCommandSectionModel
        {
            set
            {
                CommandTemplateModel = value;
                propertyChangeSend(nameof(HoldCommandSectionModel));
            }
            get
            {
                CommandTemplateModel ??= new CommandSectionModel();
                return CommandTemplateModel;
            }
        }

        public ICommand CmdSerilconnect
        {
            set
            {
                CmdSerilconnectStdin = value;
            }
            get
            {
                CmdSerilconnectStdin ??= new EasyCommand(ConnectExcuteEvent, bool () => { return true; });
                return CmdSerilconnectStdin;
            }
        }

        public ICommand CmdSerialconfigChange
        {
            set
            {
                CmdSerialconfigChangeStdin = value;
            }
            get
            {
                CmdSerialconfigChangeStdin ??= new EasyCommand(ConfigProperyChangeEvent, bool () => { return true; });
                return CmdSerialconfigChangeStdin;
            }
        }

        public ICommand CmdSerialcommandAdd
        {
            set
            {
                CmdSerialcommandAddStdin = value;
            }
            get
            {
                CmdSerialcommandAddStdin ??= new EasyCommand(CommandAddedEvent, bool () => { return true; });
                return CmdSerialcommandAddStdin;
            }
        }

        public ICommand CmdSerialcommandTake
        {
            set
            {
                CmdSerialcommandTakeStdin = value;
            }
            get
            {
                CmdSerialcommandTakeStdin ??= new EasyCommand(CommandTakeEvent, bool () => { return true; });
                return CmdSerialcommandTakeStdin;
            }
        }

        public ICommand CmdSerialcommandIndex
        {
            set
            {
                CmdSerialcommandIndexStdin = value;
            }
            get
            {
                CmdSerialcommandIndexStdin ??= new EasyCommand(CommandIndexEvent, bool () => { return true; });
                return CmdSerialcommandIndexStdin;
            }
        }

        public ICommand CmdSerialcommandWrite
        {
            set
            {
                CmdSerialcommandWriteStdin = value;
            }
            get
            {
                CmdSerialcommandWriteStdin ??= new EasyCommand(CommandWriteEvent, bool () => { return true; });
                return CmdSerialcommandWriteStdin;
            }
        }

        public ICommand CmdSerialcommandMode
        {
            set
            {
                CmdSerialcommandModeStdin = value;
            }
            get
            {
                CmdSerialcommandModeStdin ??= new EasyCommand(CommandModeEvent, bool () => { return true; });
                return CmdSerialcommandModeStdin;
            }
        }

        public ICommand CmdSerialcommandImport
        {
            set
            {
                CmdSerialcommandImportStdin = value;
            }
            get
            {
                CmdSerialcommandImportStdin ??= new EasyCommand(CommandImportEvent, bool () => { return true; });
                return CmdSerialcommandImportStdin;
            }
        }

        public ICommand CmdSerialcommandEdit
        {
            set
            {
                CmdSerialcommandEditStdin = value;
            }
            get
            {
                CmdSerialcommandEditStdin ??= new EasyCommand(CommandEditEvent, bool () => { return true; });
                return CmdSerialcommandEditStdin;
            }
        }

        //  下拉框期望展示的默认选项
        public string SelectedSerialProt
        {
            set
            {
                SelectedSerialProtStdin = value;
                propertyChangeSend(nameof(SelectedSerialProt));
            }
            get
            {
                return SelectedSerialProtStdin;
            }
        }
        
        public string SelectedBaudRate
        {
            set
            {
                SelectedBaudRateStdin = value;
                propertyChangeSend(nameof(SelectedBaudRate));
            }
            get
            {
                return SelectedBaudRateStdin;
            }
        }
        
        public string SelectedDataBit
        {
            set
            {
                SelectedDataBitStdin = value;
                propertyChangeSend(nameof(SelectedDataBit));
            }
            get
            {
                return SelectedDataBitStdin;
            }
        }
        
        public string SelectedParityBit
        {
            set
            {
                SelectedParityBitStdin = value;
                propertyChangeSend(nameof(SelectedParityBit));
            }
            get
            {
                return SelectedParityBitStdin;
            }
        }
        
        public string SelectedStopBit
        {
            set
            {
                SelectedStopBitStdin = value;
                propertyChangeSend(nameof(SelectedStopBit));
            }
            get
            {
                return SelectedStopBitStdin;
            }
        }
        
        public string SelectedHandShake
        {
            set
            {
                SelectedHandShakeStdin = value;
                propertyChangeSend(nameof(SelectedHandShake));
            }
            get
            {
                return SelectedHandShakeStdin;
            }
        }

        public string ExecuteButtonText
        {
            set
            {
                ExecuteButtonTextStdin = value;
                propertyChangeSend(nameof(ExecuteButtonText));
            }
            get
            {
                return ExecuteButtonTextStdin;
            }
        }

        public SelectionMode VarbinListBoxMode
        {
            set
            {
                VarbinListBoxModeStdin = value;
                propertyChangeSend(nameof(VarbinListBoxMode));
            }
            get
            {
                return VarbinListBoxModeStdin;
            }
        }

        public string VarbinListBoxModeName
        {
            set
            {
                VarbinListBoxModeNameStdin = value;
                propertyChangeSend(nameof(VarbinListBoxModeName));
            }
            get
            {
                return VarbinListBoxModeNameStdin;
            }
        }

        public CommandStruct VarbinCurrentItem //  缓存当前选中的指令项
        {
            set
            {
                VarbinCurrentItemStdin = value;
                propertyChangeSend(nameof(VarbinCurrentItem));
            }
            get
            {
                VarbinCurrentItemStdin ??= new CommandStruct();
                return VarbinCurrentItemStdin;
            }
        }

        //  所有的可用串口及其其他可配置属性
        public ObservableCollection<string> SerialProts { set; get; } = [];

        public ObservableCollection<string> BaudRates { set; get; } = [];

        public ObservableCollection<string> DataBits { set; get; } = [];
        
        public ObservableCollection<string> ParityBits { set; get; } = [];

        public ObservableCollection<string> StopBits { set; get; } = [];

        public ObservableCollection<string> HandShakes { set; get; } = [];

        public ObservableCollection<CommandStruct> CommandListItems { set; get; } = []; //  指令项集合

        public ObservableCollection<KeyValuePairSealed> CommandImportSources { set; get; } = [];

        private static async void MvvmMessageProcessPlant(object recipient, MvvmMessage message)
        {
            SerialViewModel self = (SerialViewModel)recipient;
            switch (message.Type)
            {
                case MvvmMessage.MvvmType.Command_EditInfoSend:
                    await self.CommandChangeEvent(message);
                    break;
            }
        }

        //  指令新增
        private void CommandAddedEvent(object? param)
        {
            try
            {
                CommandStruct NewListItem = new("", 0, "");
                CommandListItems.Add(NewListItem);
                VarbinCurrentItem = NewListItem;
            } 
            catch (Exception error)
            {
                Logger.Print(RuntimeLog.LogType.Error, $"{MethodBase.GetCurrentMethod()?.Name} Error: {error.Message}");
            }
        }

        //  指令删除
        private async void CommandTakeEvent(object? param)
        {
            try
            {
                DB.DB_TYPE DBTYPE = await DataBaseServer.CheckDBSurvival(DB.G_MapKeyName(DB.DB_MAPKEY.LocalDataCache));

                if (DBTYPE == DB.DB_TYPE.DB_Cloud)
                {
                    if (DataBaseServer.GetCloudDB() is not null and Supabase.Client CloudDB)
                    {
                        List<string> commandTakes = [.. HoldCommandSectionModel.CommandSelectionsCache.Select(x => x.Command)];

                        await CloudDB.From<SerialCommand>()
                                .Filter("command_name", Supabase.Postgrest.Constants.Operator.In, commandTakes)
                                .Delete();

                        foreach (var _struct in HoldCommandSectionModel.CommandSelectionsCache)
                        {
                            CommandListItems.Remove(_struct);
                        }
                    }
                        
                }
                else if (DBTYPE == DB.DB_TYPE.DB_Local)
                {
                    List<string> commandTakeSqls = [.. HoldCommandSectionModel.CommandSelectionsCache.Select(x=>
                                                $"DELETE FROM serial_command WHERE command_name='{x.Command}'")];
                    List<CommandStruct> backDatas = [.. HoldCommandSectionModel.CommandSelectionsCache];

                    var deleteResult = await DataBaseServer.LocalDBQuery(commandTakeSqls);
                    if (deleteResult.ErrorHint is null)
                    {
                        foreach (var _struct in HoldCommandSectionModel.CommandSelectionsCache)
                        {
                            CommandListItems.Remove(_struct);
                        }
                    }
                    HoldCommandSectionModel.CommandSelectionsCache.Clear();
                        
                }
            } 
            catch (Exception error)
            {
                Logger.Print(RuntimeLog.LogType.Error, $"{MethodBase.GetCurrentMethod()?.Name} Error: {error.Message}");
            }
        }

        //  指令索引更改，获取更改指令集合
        private void CommandIndexEvent(object? param)
        {

            if (param != null && param is List<CommandStruct> commandStructs)
            {
                HoldCommandSectionModel.CommandSelectionsCache = commandStructs.ToList() ?? [];
            }
        }

        //  指令编辑信息发送至OverView展示
        private void CommandEditEvent(object? param)
        {
            if (param is not null and AlterCommandStruct EditInfo)
            {
                WeakReferenceMessenger.Default.Send<MvvmMessage>(new MvvmMessage(MvvmMessage.MvvmType.Command_EditInfoGet, EditInfo));
            }
        }

        //  单个指令更新
        private async Task CommandChangeEvent(MvvmMessage message)
        {
            try
            {
                if (message.MsgBody is not null and AlterCommandStruct CommandAlterCache &&
                    CommandAlterCache.AlterIndex != -1 &&
                    CommandListItems.Count > CommandAlterCache.AlterIndex)
                {
                    int ChangeIndex = CommandAlterCache.AlterIndex;
                    string OldCommand = CommandListItems[ChangeIndex].Command;
                    string NewCommand = CommandAlterCache.AlterCommand.Command;
                    int NewDuration = CommandAlterCache.AlterCommand.Duration;
                    string NewAlias = CommandAlterCache.AlterCommand.Alias;

                    DB.DB_TYPE DBTYPE = await DataBaseServer.CheckDBSurvival(DB.G_MapKeyName(DB.DB_MAPKEY.LocalDataCache));

                    if (DBTYPE == DB.DB_TYPE.DB_Cloud)
                    {
                        if (DataBaseServer.GetCloudDB() is not null and Supabase.Client CloudDB)
                        {
                            Action<double, string> _process = await CustomMessageBox.Show(new CustomMessageBox.ShowyPrograssSetting
                            {
                                Msg_Minnum = 0,
                                Msg_Maxnum = 3,
                                Msg_DelayExitTime = 200
                            });

                            SerialCommand data = new()
                            {
                                Commandname = NewCommand,
                                Commandalias = NewAlias,
                                Commandinterval = NewDuration.GetSafetyChar()
                            };
                            var QueryResponse = await CloudDB.From<SerialCommand>()
                                .Where(x => x.Commandname == OldCommand)
                                .Get();

                            async Task SaveCommand()
                            {
                                if (QueryResponse.ResponseMessage is not null &&
                                QueryResponse.ResponseMessage.IsSuccessStatusCode &&
                                QueryResponse.Model is not null)
                                {
                                    await CloudDB.From<SerialCommand>()
                                        .Set(x => x.Commandinterval, NewDuration.GetSafetyChar())
                                        .Set(x => x.Commandalias, NewAlias)
                                        .Set(x => x.Commandname, NewCommand)
                                        .Where(x => x.Commandname == OldCommand)
                                        .Update();

                                    _process.Invoke(2, "执行中...");
                                }
                                else
                                {
                                    if (!string.IsNullOrEmpty(NewCommand))
                                    {
                                        await CloudDB.From<SerialCommand>().Insert(data);
                                        _process.Invoke(2, "执行中...");
                                    }
                                }
                            }
                            _process.Invoke(1, "执行中...");

                            await DataBaseServer.CloudAnchorChannel<SerialCommand>(async () =>
                            {
                                var QueryResponse = await CloudDB.From<SerialCommand>()
                                                    .Where(x => x.Commandname == NewCommand)
                                                    .Get();

                                if (QueryResponse.Model is not null &&
                                    QueryResponse.Model.Commandname == NewCommand)
                                {
                                    _process.Invoke(3, "执行完成");
                                }
                            },
                            async () =>
                            {
                                await SaveCommand();
                            },

                            () =>
                            {
                                _process.Invoke(3, "执行失败，检查网络");
                            });
                        }
                    }

                    else if (DBTYPE == DB.DB_TYPE.DB_Local)
                    {
                        string queryCommandSql = $"SELECT * FROM serial_command WHERE command_name='{OldCommand}'";

                        string updateCommandSql = "UPDATE serial_command SET " +
                                                    $"command_name = '{NewCommand}'," +
                                                    $"command_interval = '{NewDuration}', " +
                                                    $"command_alias = '{NewAlias}' " +
                                                    $"WHERE command_name='{OldCommand}'";

                        string insertCommandSql = $"INSERT INTO serial_command VALUES(" +
                                                    $"'{NewCommand}'," + $"'{NewAlias}'," + $"'{NewDuration}')";

                        if (await DataBaseServer.LocalDBQueryFree(queryCommandSql) is var queryResult && queryResult != null)
                        {
                            bool isRollBack = false;
                            if (queryResult.ErrorHint == null && queryResult.Result.TryGetValue(queryCommandSql, out Dictionary<string, ICollection<object>>? data) &&
                                data.TryGetValue("command_name", out ICollection<object>? commands) &&
                                commands.Count != 0)
                            {
                                Logger.Information("execute command update");
                                if (DataBaseServer.LocalDBQueryFree(updateCommandSql) == null)
                                {
                                    isRollBack = true;
                                }
                                Logger.Print(RuntimeLog.LogType.Debug, $"info update to sql success, where index {ChangeIndex}");
                            }
                            else
                            {
                                if (DataBaseServer.LocalDBQueryFree(insertCommandSql) == null)
                                {
                                    isRollBack = true;
                                }
                                else
                                {
                                    Logger.Print(RuntimeLog.LogType.Debug, $"info write to sql success, where index {ChangeIndex}");
                                }
                            }
                            if (isRollBack)
                            {
                                CommandListItems[ChangeIndex] = new CommandStruct(
                                CommandListItems[ChangeIndex].Command,
                                CommandListItems[ChangeIndex].Duration,
                                CommandListItems[ChangeIndex].Alias,
                                CommandListItems[ChangeIndex].Order); //  Rollback Sql
                                Logger.Error($"info write to sql encount error, rollback now, where index {ChangeIndex}");
                            }
                        }

                    }
                }
            }
            catch (Exception error)
            {
                Logger.Print(RuntimeLog.LogType.Error, $"{MethodBase.GetCurrentMethod()?.Name} Error: {error.Message}");
            }
        }

        //  指令执行
        private void CommandWriteEvent(object? param)
        {
            PowerPlantServer.Write(HoldCommandSectionModel.CommandSelectionsCache);
        }

        //  指令选中模式
        private void CommandModeEvent(object? param)
        {
            Application.Current.Dispatcher.InvokeAsync(() =>
            {
                switch (VarbinListBoxModeName)
                {
                    case "\ue64b":
                        VarbinListBoxModeName = "\ue653";
                        VarbinListBoxMode = SelectionMode.Extended;
                        break;

                    case "\ue653":
                        VarbinListBoxModeName = "\ue64b";
                        VarbinListBoxMode = SelectionMode.Single;
                        break;
                }

            });
            Logger.Print(RuntimeLog.LogType.Debug, "comamnd listbox mode change, where model: ", VarbinListBoxMode);
        }

        private void CommandImportEvent(object? param)
        {
            Application.Current.Dispatcher.InvokeAsync(async () =>
            {
                ICollection<KeyValuePair<string, string>> Commands = [];

                foreach(var kvp in ActivityAssistBehivor.Behivor.AttributeExpectsMap)
                {
                    if (param is not null and ICollection<string> selects && selects.Count > 0)
                    {
                        if (ActivityAssistBehivor.Behivor.ProductFlagChzMap.GetSafetyKey(selects.ElementAt(0)) is ICollection<ProductFlag> flags &&
                            flags.Count == 1)
                        {
                            if (kvp.Key == $"{nameof(TestItemDeepSeatedSealed.Command)}-{flags.ElementAt(0)}")
                            {
                                foreach (var command in kvp.Value)
                                {
                                    if (command.Contains('='))
                                    {
                                        if (command.Split('=').Last().Length > 0)
                                        {
                                            Commands.Add(new KeyValuePair<string, string>(command, command.Split('=').Last()));
                                        }
                                        else
                                        {
                                            Commands.Add(new KeyValuePair<string, string>(command, command.Split('=').First()));
                                        }
                                    }
                                    else if (command.Contains('+'))
                                    {
                                        Commands.Add(new KeyValuePair<string, string>(command, command.Split('+').Last()));
                                    }
                                }
                            }
                        }
                    }
                }

                DB.DB_TYPE DBTYPE = await DataBaseServer.CheckDBSurvival(DB.G_MapKeyName(DB.DB_MAPKEY.LocalDataCache));

                if (DBTYPE == DB.DB_TYPE.DB_Cloud)
                {
                    List<SerialCommand> ValidCommand = [.. Commands.Select(x => new SerialCommand
                    {
                        Commandname = x.Key,
                        Commandalias = x.Value
                    })];

                    if (DataBaseServer.GetCloudDB() is not null and Supabase.Client CloudDB)
                    {
                        var InsertResponse = await CloudDB.From<SerialCommand>()
                            .Insert(ValidCommand);

                        await DataBaseServer.CloudAnchorChannel<SerialCommand>(() =>
                        {
                            GetCommandInfo();

                            Logger.Print(RuntimeLog.LogType.Debug, "command save success");
                        },
                        () => { },
                        () =>
                        {
                            Logger.Print(RuntimeLog.LogType.Error, "command save fail");
                        });
                    }
                }

                else if (DBTYPE == DB.DB_TYPE.DB_Local)
                {
                    List<string> ValidCommand = [.. Commands.Select(x => 
                                                $"INSERT INTO serial_command VALUES(" +
                                                $"'{x.Key}'," + $"'{x.Value}'," + $"'')")];

                    if (await DataBaseServer.LocalDBQuery(ValidCommand) is var queryResult && 
                        queryResult != null &&
                        queryResult.ErrorHint == null)
                    {
                        GetCommandInfo();

                        Logger.Print(RuntimeLog.LogType.Debug, ["command save success"]);
                    }
                }
            });

     
        }

        private void LoadCommandImportItems()
        {
            Application.Current.Dispatcher.Invoke(() =>
            {
                CommandImportSources.Clear();

                foreach (var i in ActivityAssistBehivor.Behivor.ProductFlagChzMap)
                {
                    CommandImportSources.Add(new KeyValuePairSealed("\ue691", i.Value, "BurgundyNight".FindSolidBrush()));
                }
                propertyChangeSend(nameof(CommandImportSources));
            });
        }

        //  串口连接
        private async void ConnectExcuteEvent(object? param)
        {
            try
            {
                if (PowerPlantServer.Action(2).Item1)
                {
                    var _action = PowerPlantServer.Action(0);
                    if (_action.Item1)
                    {
                        ExecuteButtonText = "连接";
                    }
                    else
                    {
                        await CustomMessageBox.Show(
                            new CustomMessageBox.InquiryNmPopupSetting
                            {
                                Msg_Title = "警告",
                                Msg_InquiryIcon = 1,
                                Msg_InquiryButtoms = ["知道了"],
                                Msg_BodyText = _action.Item2
                            });
                    }
                }
                else
                {
                    await SaveFromConfig();
                    var _action = PowerPlantServer.Action(1);
                    if (_action.Item1 && string.IsNullOrEmpty(_action.Item2))
                    {
                        Logger.Information("serial open success");
                        ExecuteButtonText = "关闭";
                    }
                    else
                    {
                        await CustomMessageBox.Show(
                            new CustomMessageBox.InquiryNmPopupSetting
                            {
                                Msg_Title = "警告",
                                Msg_InquiryIcon = 1,
                                Msg_InquiryButtoms = ["知道了"],
                                Msg_BodyText = _action.Item2
                            });

                    }
                }
            }
            catch (Exception error)
            {
                Logger.Print(RuntimeLog.LogType.Error, $"{MethodBase.GetCurrentMethod()?.Name} Error: {error.Message}");
            }
        }

        //  保存串口连接配置
        private async Task SaveFromConfig()
        {
            try
            {
                await Application.Current.Dispatcher.InvokeAsync(async () =>
                {
                    if (!string.IsNullOrEmpty(ConfigSelectedRecord.Com.PortName) &&
                        SerialConfigInfoMap.Com.SerialComNameMap.TryGetValue(ConfigSelectedRecord.Com.PortName, out string? portName) &&
                        portName is not null)
                    {
                        PowerPlantServer.Instance((serial) =>
                        {
                            serial.PortName = portName;
                            serial.BaudRate = ConfigSelectedRecord.Com.BaudRate;
                            serial.DataBits = ConfigSelectedRecord.Com.DataBit;
                            serial.Parity = ConfigSelectedRecord.Com.ParityBit;
                            serial.StopBits = ConfigSelectedRecord.Com.StopBit;
                            serial.Handshake = ConfigSelectedRecord.Com.Handshake;
                        });

                        try
                        {
                            DB.DB_TYPE DBTYPE = await DataBaseServer.CheckDBSurvival(DB.G_MapKeyName(DB.DB_MAPKEY.LocalDataCache));
                            
                                if (DBTYPE == DB.DB_TYPE.DB_Cloud &&
                                    DataBaseServer.GetCloudDB() is not null and Supabase.Client CloudDB)
                                {
                                    string Portname = ConfigSelectedRecord.Com.PortName;
                                    string Baudrate = ConfigSelectedRecord.Com.BaudRate.GetSafetyChar();
                                    string Databits = ConfigSelectedRecord.Com.DataBit.GetSafetyChar();
                                    string Stopbits = ConfigSelectedRecord.Com.StopBit.GetSafetyChar();
                                    string Paritybits = ConfigSelectedRecord.Com.ParityBit.GetSafetyChar();
                                    string Handshake = ConfigSelectedRecord.Com.Handshake.GetSafetyChar();
                                    var Query = await CloudDB.From<SerialConfig>().Get();
                                    if (Query.Models.Count > 0)
                                    {
                                        string oldPortname = Query.Models[0].Portname;

                                        await CloudDB.From<SerialConfig>()
                                            .Set(x => x.Portname, Portname)
                                            .Set(x => x.Baudrate, Baudrate)
                                            .Set(x => x.Databits, Databits)
                                            .Set(x => x.Stopbits, Stopbits)
                                            .Set(x => x.Paritybits, Paritybits)
                                            .Set(x => x.Handshake, Handshake)
                                            .Where(x => x.Portname == oldPortname)
                                            .Update();
                                    }
                                    else
                                    {
                                        var data = new SerialConfig()
                                        {
                                            Portname = ConfigSelectedRecord.Com.PortName,
                                            Baudrate = ConfigSelectedRecord.Com.BaudRate.GetSafetyChar(),
                                            Databits = ConfigSelectedRecord.Com.DataBit.GetSafetyChar(),
                                            Stopbits = ConfigSelectedRecord.Com.StopBit.GetSafetyChar(),
                                            Paritybits = ConfigSelectedRecord.Com.ParityBit.GetSafetyChar(),
                                            Handshake = ConfigSelectedRecord.Com.Handshake.GetSafetyChar()
                                        };
                                        await CloudDB.From<SerialConfig>().Insert(data);
                                    }
                                    
                                }
                                else if (DBTYPE == DB.DB_TYPE.DB_Local)
                                {
                                    string queryConfigSql = "SELECT port_name FROM serial_config";

                                    string updateConfigSql = "UPDATE serial_config SET " +
                                                            $"port_name = '{ConfigSelectedRecord.Com.PortName}'," +
                                                            $"baud_rate = '{ConfigSelectedRecord.Com.BaudRate}'," +
                                                            $"data_bits = '{ConfigSelectedRecord.Com.DataBit}'," +
                                                            $"stop_bits = '{ConfigSelectedRecord.Com.StopBit}'," +
                                                            $"parity_bits = '{ConfigSelectedRecord.Com.ParityBit}'," +
                                                            $"hand_shake = '{ConfigSelectedRecord.Com.Handshake}' ";

                                    string insertConfigSql = $"INSERT INTO serial_config VALUES(" +
                                                                $"'{ConfigSelectedRecord.Com.PortName}'," +
                                                                $"'{ConfigSelectedRecord.Com.BaudRate}'," +
                                                                $"'{ConfigSelectedRecord.Com.DataBit}'," +
                                                                $"'{ConfigSelectedRecord.Com.StopBit}'," +
                                                                $"'{ConfigSelectedRecord.Com.ParityBit}'," +
                                                                $"'{ConfigSelectedRecord.Com.Handshake}')";

                                    if (await DataBaseServer.LocalDBQueryFree(queryConfigSql) is SqliteExceuteResult queryResult &&
                                        queryResult.ErrorHint == null &&
                                        queryResult.Result.TryGetValue(queryConfigSql, out Dictionary<string, ICollection<object>>? data) &&
                                        data.Count != 0)
                                    {
                                        await DataBaseServer.LocalDBQueryFree(updateConfigSql);
                                    }
                                    else
                                    {
                                        Logger.Information("execute config insert");
                                        await DataBaseServer.LocalDBQueryFree(insertConfigSql);
                                    }
                                    
                                }
                     
                        }
                        catch (Exception error)
                        {
                            Logger.Print(RuntimeLog.LogType.Error, $"config serialport save {error.Message}");
                        }
                    }
                });
            }
            catch (Exception error)
            {
                Logger.Print(RuntimeLog.LogType.Error, $"{MethodBase.GetCurrentMethod()?.Name} Error: {error.Message}");
            }
        }

        //  数据重加载专用方法
        public async Task ReadyWork()
        {
            DB.DB_TYPE DBTYPE = await DataBaseServer.CheckDBSurvival(DB.G_MapKeyName(DB.DB_MAPKEY.LocalDataCache));
            
            if (DBTYPE == DB.DB_TYPE.DB_Cloud)
            {
                if (DataBaseServer.GetCloudDB() is not null and Supabase.Client)
                {
                    try
                    {

                        GetSerialComInfo();

                        GetCommandInfo();

                        SerialMonitor();
                    }
                    catch (Exception error)
                    {
                        Logger.Print(RuntimeLog.LogType.Debug, "ReadyWork encount error: ", error.Message);
                    }
                }
            }

            else if (DBTYPE == DB.DB_TYPE.DB_Local)
            {
                try
                {
                    await TableCreate();

                    GetSerialComInfo();

                    GetCommandInfo();

                    SerialMonitor();
                }
                catch (Exception error)
                {
                    Logger.Print(RuntimeLog.LogType.Error, $"{MethodBase.GetCurrentMethod()?.Name} Error: {error.Message}");
                }
            }

            LoadCommandImportItems();
        }

        //  加载上一次的串口配置
        private void GetSerialComInfo()
        {
            try
            {
                Application.Current.Dispatcher.InvokeAsync(async () =>
                {
                    string sqlPortName = string.Empty;
                    string sqlBaudBit = string.Empty;
                    string sqlDataBit = string.Empty;
                    string sqlStopBit = string.Empty;
                    string sqlParityBit = string.Empty;
                    string sqlHandShake = string.Empty;

                    void dispose(bool valid)
                    {
                        if (valid)
                        {
                            GetValidSerialPort(() =>
                            {
                                if (!string.IsNullOrEmpty(sqlPortName) && SerialConfigInfoMap.Com.SerialComNameMap.TryGetValue(sqlPortName, out string? realname))
                                {
                                    if (realname != null)
                                    {
                                        SelectedSerialProt = sqlPortName;
                                        propertyChangeSend(nameof(SelectedSerialProt));
                                        ConfigSelectedRecord.Com.PortName = sqlPortName;
                                    }
                                }
                                else
                                {
                                    if (SerialProts.Count > 0) SelectedSerialProt = SerialProts[0];
                                }
                            });

                            if (!string.IsNullOrEmpty(sqlBaudBit) && SerialConfigInfoMap.Com.SerialComBaudMap.TryGetValue(sqlBaudBit, out var realbaud))
                            {
                                SelectedBaudRate = sqlBaudBit;
                                propertyChangeSend(nameof(SelectedBaudRate));
                                ConfigSelectedRecord.Com.BaudRate = realbaud;
                            }
                            else
                            {
                                if (BaudRates.Count > 0) SelectedBaudRate = BaudRates[0];
                            }

                            if (!string.IsNullOrEmpty(sqlDataBit) && SerialConfigInfoMap.Com.SerialComDataMap.TryGetValue(sqlDataBit, out var realdata))
                            {
                                SelectedDataBit = sqlDataBit;
                                ConfigSelectedRecord.Com.DataBit = realdata;
                            }
                            else
                            {
                                if (DataBits.Count > 0) SelectedDataBit = DataBits[0];
                            }

                            if (!string.IsNullOrEmpty(sqlStopBit) && SerialConfigInfoMap.Com.SerialComStopMap.TryGetValue(sqlStopBit, out var realstop))
                            {
                                SelectedStopBit = sqlStopBit;
                                ConfigSelectedRecord.Com.StopBit = realstop;
                            }
                            else
                            {
                                if (StopBits.Count > 0) SelectedStopBit = StopBits[0];
                            }

                            if (!string.IsNullOrEmpty(sqlParityBit) && SerialConfigInfoMap.Com.SerialComParityMap.TryGetValue(sqlPortName, out var realparity))
                            {
                                SelectedParityBit = sqlParityBit;
                                ConfigSelectedRecord.Com.ParityBit = realparity;
                            }
                            else
                            {
                                if (ParityBits.Count > 0) SelectedParityBit = ParityBits[0];
                            }

                            if (!string.IsNullOrEmpty(sqlHandShake) && SerialConfigInfoMap.Com.SerialComHandShakeMap.TryGetValue(sqlHandShake, out var realhand))
                            {
                                SelectedHandShake = sqlHandShake;
                                ConfigSelectedRecord.Com.Handshake = realhand;
                            }
                            else
                            {
                                if (HandShakes.Count > 0) SelectedHandShake = HandShakes[0];
                            }
                        }
                        else
                        {
                            ConfigSelectedRecord.Com.PortName = SerialProts.GetSafetyChar(0) ?? string.Empty;
                            ConfigSelectedRecord.Com.BaudRate = SerialConfigInfoMap.Com.SerialComBaudMap[BaudRates[0]];
                            ConfigSelectedRecord.Com.DataBit = SerialConfigInfoMap.Com.SerialComDataMap[DataBits[0]];
                            ConfigSelectedRecord.Com.ParityBit = SerialConfigInfoMap.Com.SerialComParityMap[ParityBits[0]];
                            ConfigSelectedRecord.Com.StopBit = SerialConfigInfoMap.Com.SerialComStopMap[StopBits[0]];
                            ConfigSelectedRecord.Com.Handshake = SerialConfigInfoMap.Com.SerialComHandShakeMap[HandShakes[0]];

                            if (SerialProts.Count > 0) SelectedSerialProt = SerialProts[0];
                            if (BaudRates.Count > 0) SelectedBaudRate = "115200";
                            if (DataBits.Count > 0) SelectedDataBit = "8";
                            if (StopBits.Count > 0) SelectedStopBit = "Two";
                            if (ParityBits.Count > 0) SelectedParityBit = "None";
                            if (HandShakes.Count > 0) SelectedHandShake = "None";
                        }
                    }

                    DataBits.Clear();
                    StopBits.Clear();
                    ParityBits.Clear();
                    BaudRates.Clear();
                    HandShakes.Clear();

                    DataBits.Add(SerialServer.ReceiveSerialInfo(EmSerialInfoType.Databits));
                    StopBits.Add(SerialServer.ReceiveSerialInfo(EmSerialInfoType.StopBits));
                    ParityBits.Add(SerialServer.ReceiveSerialInfo(EmSerialInfoType.ParityBits));
                    BaudRates.Add(SerialServer.ReceiveSerialInfo(EmSerialInfoType.BundRate));
                    HandShakes.Add(SerialServer.ReceiveSerialInfo(EmSerialInfoType.HandShakes));

                    DB.DB_TYPE DBTYPE = await DataBaseServer.CheckDBSurvival(DB.G_MapKeyName(DB.DB_MAPKEY.LocalDataCache));

                    if (DBTYPE == DB.DB_TYPE.DB_Cloud)
                    {
                        if (DataBaseServer.GetCloudDB() is not null and Supabase.Client CloudDB)
                        {
                            var queryResult = await CloudDB.From<SerialConfig>().Get();

                            if (queryResult.Model is not null)
                            {
                                sqlPortName = queryResult.Model.Portname;
                                sqlBaudBit = queryResult.Model.Baudrate;
                                sqlDataBit = queryResult.Model.Databits;
                                sqlStopBit = queryResult.Model.Stopbits;
                                sqlParityBit = queryResult.Model.Paritybits;
                                sqlHandShake = queryResult.Model.Handshake;
                            }
                        }
                    }

                    else if (DBTYPE == DB.DB_TYPE.DB_Local)
                    {
                        string queryConfigSql = "SELECT * FROM serial_config";
                        var queryResult = await DataBaseServer.LocalDBQueryFree(queryConfigSql);

                        if (queryResult.ErrorHint == null && queryResult.Result.TryGetValue(queryConfigSql, out Dictionary<string, ICollection<object>>? Data))
                        {
                            sqlPortName = Data["port_name"].GetSafetyChar(0);
                            sqlBaudBit = Data["baud_rate"].GetSafetyChar(0);
                            sqlDataBit = Data["data_bits"].GetSafetyChar(0);
                            sqlStopBit = Data["stop_bits"].GetSafetyChar(0);
                            sqlParityBit = Data["parity_bits"].GetSafetyChar(0);
                            sqlHandShake = Data["hand_shake"].GetSafetyChar(0);
                        }

                    }
                    dispose(!string.IsNullOrEmpty(sqlPortName));
                });
            }
            catch (Exception error)
            {
                Logger.Print(RuntimeLog.LogType.Error, $"{MethodBase.GetCurrentMethod()?.Name} Error: {error.Message}");
            }
        }

        //  获取有效串口名
        private void GetValidSerialPort(Action? CallBack = null)
        {
            Application.Current.Dispatcher.InvokeAsync(async () =>
            {
                ManagementObjectSearcher Cominfos = new(@"SELECT * FROM Win32_PnPEntity WHERE NAME LIKE '%COM%'");

                ICollection<string> Ports = await Cominfos.Com();

                if (!Ports.SequenceEqual(SerialProts))
                {
                    SerialProts.Clear();
                    SerialProts.Add(Ports);
                    CallBack?.Invoke();
                }
                
            }, DispatcherPriority.Background);
        }

        //  创建sqlite数据库
        private async Task TableCreate()
        {
            await Task.Run(async () =>
            {
                try
                {
                    string verityTableSql = "select name from sqlite_master where type='table'";
                    var sqltablecreate = await DataBaseServer.LocalDBQueryFree(verityTableSql);
                    List<string> unexistsTables = [];
                    foreach (var key in HoldConfigSectionModel.TableReserveDuty.Keys)
                    {
                        if (sqltablecreate.ErrorHint == null && sqltablecreate.Result.TryGetValue(verityTableSql, out var keyValues))
                        {
                            if (keyValues.TryGetValue("name", out ICollection<object>? tables) && tables is not null)
                            {
                                if (!tables.Contains(key)) unexistsTables.Add(HoldConfigSectionModel.TableReserveDuty[key]);
                            }
                            else
                            {
                                unexistsTables.Add(HoldConfigSectionModel.TableReserveDuty[key]);
                            }
                        }
                        else
                        {
                            unexistsTables.Add(HoldConfigSectionModel.TableReserveDuty[key]);
                        }
                    }

                    if (await DataBaseServer.LocalDBQuery(unexistsTables) is SqliteExceuteResult result &&
                        result.ErrorHint == null)
                    {
                        Logger.Debug("dispose sql of table create");
                    }
                    else
                    {
                        Logger.Error("table create fail");
                    }
                }
                catch (Exception error)
                {
                    Logger.Print(RuntimeLog.LogType.Error, $"{MethodBase.GetCurrentMethod()?.Name} Error: {error.Message}");
                }
            }).ConfigureAwait(false);
        }

        //  加载指令数据
        private async void GetCommandInfo()
        {
            await Task.Delay(200);

            try
            {
                DB.DB_TYPE DBTYPE = await DataBaseServer.CheckDBSurvival(DB.G_MapKeyName(DB.DB_MAPKEY.LocalDataCache));

                if (DBTYPE == DB.DB_TYPE.DB_Cloud)
                {
                    if (DataBaseServer.GetCloudDB() is not null and Supabase.Client CloudDB)
                    {
                        var queryResult = await CloudDB.From<SerialCommand>().Get();
                        Application.Current.Dispatcher.Invoke(() =>
                        {
                            CommandListItems.Clear();
                        });

                        await Application.Current.Dispatcher.InvokeAsync(() =>
                        {

                            foreach (var model in queryResult.Models)
                            {
                                string command_name = model.Commandname;
                                string command_alias = model.Commandalias;
                                string command_interval = model.Commandinterval;

                                if (int.TryParse(command_interval, out int interval) && !string.IsNullOrEmpty(command_name))
                                {
                                    CommandListItems.Add(new CommandStruct(command_name, interval, command_alias));
                                }

                                else if (!command_interval.IsAbsoluteValidValue())
                                {
                                    CommandListItems.Add(new CommandStruct(command_name, 0, command_alias));
                                }
                            }
                        });
                    }
                }

                else if (DBTYPE == DB.DB_TYPE.DB_Local)
                {
                    string queryConfigSql = "SELECT * FROM serial_command";

                    var queryResult = await DataBaseServer.LocalDBQueryFree(queryConfigSql);

                    await Task.Delay(40).ContinueWith(_ =>
                    {
                        if (queryResult.ErrorHint == null &&
                            queryResult.Result.TryGetValue(queryConfigSql, out Dictionary<string, ICollection<object>>? CommandDict))
                        {
                            Application.Current.Dispatcher.InvokeAsync(() =>
                            {
                                CommandListItems.Clear();

                                int indexof = 0;
                                foreach (var name in CommandDict["command_name"])
                                {
                                    string command_name = name.ToString() ?? string.Empty;
                                    string command_alias = CommandDict["command_alias"].GetSafetyChar(indexof);
                                    string command_interval = CommandDict["command_interval"].GetSafetyChar(indexof);

                                    if (int.TryParse(command_interval, out int interval) && !string.IsNullOrEmpty(command_name))
                                    {
                                        Application.Current.Dispatcher.InvokeAsync(() =>
                                        {
                                            CommandListItems.Add(new CommandStruct(command_name, interval, command_alias));
                                        });
                                    }
                                    else if (!command_interval.IsAbsoluteValidValue())
                                    {
                                        CommandListItems.Add(new CommandStruct(command_name, 0, command_alias));
                                    }
                                    indexof++;
                                }
                            });
                        }
                    });
                }
            }
            catch (Exception error)
            {
                Logger.Print(RuntimeLog.LogType.Error, $"{MethodBase.GetCurrentMethod()?.Name} Error: {error.Message}");
            }
        }

        //  监听串口变化
        private void SerialMonitor()
        {
            PowerPlantServer.Moniter(null, 1, true);

            PowerPlantServer.Moniter((isAdd) =>
            {
                if (isAdd)
                {
                    //  获取有效串口名
                    GetValidSerialPort(() =>
                    {
                        //  如果重新插入的串口为之前使用过的串口，则主动打开它
                        if (SerialConfigInfoMap.Com.SerialComNameMap.GetSafetyKey<string, string>(PowerPlantServer.Name()) is not null and
                            ICollection<string> _PortNames && _PortNames.Count == 1 &&
                            SerialProts.Contains(_PortNames.ElementAt(0)))
                        {
                            Application.Current.Dispatcher.InvokeAsync(() =>
                            {
                                PowerPlantServer.Action(1);
                                if (PowerPlantServer.Action(2).Item1)
                                {
                                    ExecuteButtonText = "关闭";
                                }
                                SelectedSerialProt = _PortNames.ElementAt(0);
                            });
                        }
                    });
                }
                else
                {
                    GetValidSerialPort(() =>
                    {
                        if (!PowerPlantServer.Action(2).Item1)
                        {
                            Application.Current.Dispatcher.Invoke(() =>
                            {
                                ExecuteButtonText = "连接";
                            });
                        }
                    });
                }
            }, 0, true);
        }

        //  更新窗口信息。但发生选中事件时触发
        private void ConfigProperyChangeEvent(object? objects)
        {
            try
            {
                bool isOpen = PowerPlantServer.Action(2).Item1;
                if (isOpen) PowerPlantServer.Action(0);

                if (SelectedSerialProt is not null && SerialConfigInfoMap.Com.SerialComNameMap.TryGetValue(SelectedSerialProt, out string? port))
                {
                    ConfigSelectedRecord.Com.PortName = SelectedSerialProt;
                    PowerPlantServer.Instance((serial) => { serial.PortName = port; });
                }

                if (SelectedBaudRate is not null && SerialConfigInfoMap.Com.SerialComBaudMap.TryGetValue(SelectedBaudRate, out int baud))
                {
                    ConfigSelectedRecord.Com.BaudRate = baud;
                    PowerPlantServer.Instance((serial) => { serial.BaudRate = baud; });
                }
                if (SelectedDataBit is not null && SerialConfigInfoMap.Com.SerialComDataMap.TryGetValue(SelectedDataBit, out int data))
                {
                    ConfigSelectedRecord.Com.DataBit = data;
                    PowerPlantServer.Instance((serial) => { serial.DataBits = data; });
                }
                if (SelectedStopBit is not null && SerialConfigInfoMap.Com.SerialComStopMap.TryGetValue(SelectedStopBit, out StopBits stop))
                {
                    ConfigSelectedRecord.Com.StopBit = stop;
                    PowerPlantServer.Instance((serial) => { serial.StopBits = stop; });
                }
                if (SelectedParityBit is not null && SerialConfigInfoMap.Com.SerialComParityMap.TryGetValue(SelectedParityBit, out Parity parity))
                {
                    ConfigSelectedRecord.Com.ParityBit = parity;
                    PowerPlantServer.Instance((serial) => { serial.Parity = parity; });
                }
                if (SelectedHandShake is not null && SerialConfigInfoMap.Com.SerialComHandShakeMap.TryGetValue(SelectedHandShake, out Handshake hand))
                {
                    ConfigSelectedRecord.Com.Handshake = hand;
                    PowerPlantServer.Instance((serial) => { serial.Handshake = hand; });
                }

                if (isOpen)
                {
                    bool _isOpen = PowerPlantServer.Action(1).Item1;
                }
            }
            catch (Exception error)
            {
                Logger.Print(RuntimeLog.LogType.Error, $"{MethodBase.GetCurrentMethod()?.Name} Error: {error.Message}");
            }
        }

    }
}
